<?php

// ------------------------------------------------------------------------
// |@Author       : Jarmin <edshop@qq.com>
// |@----------------------------------------------------------------------
// |@Date         : 2025-04-07 19:28:32
// |@----------------------------------------------------------------------
// |@LastEditTime : 2025-04-27 02:29:10
// |@----------------------------------------------------------------------
// |@LastEditors  : Jarmin <jarmin@ladmin.cn>
// |@----------------------------------------------------------------------
// |@Description  : 服务层基类，提供仓储自动加载功能
// |@----------------------------------------------------------------------
// |@FilePath     : Service.php
// |@----------------------------------------------------------------------
// |@Copyright (c) 2025 http://www.ladmin.cn   All rights reserved.
// ------------------------------------------------------------------------

namespace think\admin;

use stdClass;
use think\App;
use think\Request;
use think\helper\Str;

/**
 * 服务层基类
 *
 * 提供基础服务功能，包括：
 * - 仓储类自动加载
 * - 统一异常处理
 *
 * @package think\admin
 */
abstract class Service extends stdClass
{
    /**
     * 应用实例
     * @var App
     */
    protected App $app;

    /**
     * 构造函数
     * @param App $app 应用实例
     */
    public function __construct(App $app)
    {
        $this->app = $app;
        $this->request = $app->request;
    }

    /**
     * 魔术方法-自动加载服务类和仓储类
     *
     * 通过动态属性访问自动加载服务类或仓储类实例
     * 匹配规则：
     * - service开头的属性名加载服务类(如$this->serviceUser)
     * - repository开头的属性名加载仓储类(如$this->repositoryUser)
     *
     * @param string $name 属性名，格式为"serviceXxx"或"repositoryXxx"
     * @return mixed 返回服务类或仓储类实例
     * @throws HttpResponseException 当类不存在时抛出异常
     *
     * @example
     *   // 加载User服务类
     *   $userService = $this->serviceUser;
     *   // 加载User仓储类
     *   $userRepository = $this->repositoryUser;
     */
    public function __get(string $name): mixed
    {
        if (preg_match('/^service(\w+)$/i', $name, $matches)) {
            $className = Str::studly($matches[1]);
            return $this->loadService($className);
        }
        if (preg_match('/^repository(\w+)$/i', $name, $matches)) {
            $className = Str::studly($matches[1]);
            return $this->loadRepository($className);
        }
    }

    /**
     * 加载服务类
     *
     * 按照以下顺序查找服务类：
     * 1. think\admin\service 命名空间下
     * 2. 应用自定义服务类
     *
     * @param string $className 服务类名
     * @return mixed 服务类实例
     * @throws \think\exception\HttpResponseException 服务类不存在时抛出异常
     */
    protected function loadService(string $className): mixed
    {
        $services = [
            "\\think\\admin\\service\\{$className}",
            $this->app->parseClass('service', $className)
        ];
        foreach ($services as $class) {
            if (class_exists($class)) {
                return $this->app->make($class);
            }
        }
        $this->error(500, lang('system.error_service_not_found', ['class' => $className]));
    }

    /**
     * 加载仓储类
     *
     * 按照以下顺序查找仓储类：
     * 1. think\admin\repository 命名空间下
     * 2. 应用自定义仓储类
     *
     * @param string $className 仓储类名
     * @return mixed
     * @throws HttpResponseException 当仓储类不存在时抛出异常
     */
    protected function loadRepository(string $className): mixed
    {
        $repositorys = [
            "\\think\\admin\\repository\\{$className}",
            $this->app->parseClass('repository', $className),
        ];

        foreach ($repositorys as $class) {
            if (class_exists($class)) {
                return $this->app->make($class);
            }
        }
        throw_response(500, lang('system.error_repository_not_found', ['class' => $className]));
    }
}
